#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "utils.h"

/*
 * SIOCSIFHWADDR 设置接口mac地址
 * SIOCGIFHWADDR 获取接口mac地址
 *
 * SIOCSIFADDR 设置接口ip地址
 * SIOCGIFADDR 获取接口ip地址
 *
 * SIOCGIFFLAGS 获取接口标志
 * SIOCSIFFLAGS 设置接口标志
 *
 * SIOCGIFNETMASK 获取接口子网掩码
 * SIOCSIFNETMASK 设置接口子网掩码
 *
 * SIOCGIFMETRIC 获取接口metric
 * SIOCSIFMETRIC 设置接口metric
 */
int get_ifreq(char * inf, int siocgif_xxx, struct ifreq * ifr) {
	int sock;

	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock == -1) {
		return -1;
	}

	strcpy(ifr->ifr_name, inf);

	if (ioctl(sock, siocgif_xxx, ifr) < 0) {
		close(sock);
		return -1;
	}
	close(sock);

	return 0;
}

int get_if_mac(char * inf, char * mac) {
	struct ifreq ifr;
	int ret = -1;
	unsigned char * hwaddr = NULL;

	ret = get_ifreq(inf, SIOCGIFHWADDR, &ifr);
	if (ret != 0) return ret;

    hwaddr = (unsigned char *) (ifr.ifr_hwaddr.sa_data);
    memcpy(mac, hwaddr, 6);

	return 0;
}

/**
 * @brief:	用来获取 SIOCGIFADDR, SIOCGIFNETMASK, SIOCGIFGW
 *
 * @param inf
 * @param siocgif_xxx 仅限获取 addr, broadcastaddr, netmask, gw等
 * @param buf
 *
 * @return 
 */
int get_if_sockaddr(char * inf, int siocgif_xxx, char * buf) {
	struct ifreq ifr;
	int ret = -1;
	struct sockaddr_in * sin;

	ret = get_ifreq(inf, siocgif_xxx, &ifr);
	if (ret != 0) return ret;

	sin = (struct sockaddr_in *) &ifr.ifr_addr;
	snprintf((char *)buf, INET_ADDRSTRLEN/*INET6_ADDRSTRLEN*/, "%s", inet_ntoa(sin->sin_addr));

	return 0;
}

/*
 * /usr/include/net/if.h
 */
int get_if_flag(char * inf, unsigned int *flag) {
	struct ifreq ifr;
	int ret = -1;

	ret = get_ifreq(inf, SIOCGIFFLAGS, &ifr);
	if (ret != 0) return ret;

	*flag = ifr.ifr_flags;

	return 0;
}

int is_valid_ip(unsigned char * ipaddr) {
	int ret = 0;
	struct in_addr inp;

	return (0 != inet_aton((const char *)ipaddr, &inp));
}

int is_valid_netmask(unsigned char * netmask) {
	unsigned int b = 0, i, n[4];

	if(is_valid_ip(netmask) == 0) return 0;

	sscanf((const char *)netmask, "%u.%u.%u.%u", &n[3], &n[2], &n[1], &n[0]);

	for(i = 0; i < 4; ++i) {
		b += n[i] << (i * 8);
	}
	b = ~b + 1;

	return ((b & (b - 1)) == 0);
}

/**
 * @brief:	
 *
 * @param inf
 * @param proto 1 dhcp
 *
 * @return 
 */
int get_if_proto(char * inf, int * proto) {
	char cmd[256] = {0};
	char buf[256] = {0};
	FILE * f = NULL;
	int nread = 0;
	unsigned int hex;

	/*0x1103*/
	sprintf(cmd, "cat /sys/class/net/%s/flags", inf);
	if (0 >= popen_cmd(cmd, buf, sizeof(buf)/sizeof(buf[0])))
		return -1;

	sscanf(buf, "%x", &hex);

	*proto = hex & 0x1;

	return 0;
}
